package com.indi.gulimall.product.service.impl;

import com.alibaba.fastjson.TypeReference;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.indi.common.constant.ProductConstant.ProductStatusEnum;
import com.indi.common.to.SkuReductionTO;
import com.indi.common.to.SkuStockTO;
import com.indi.common.to.SpuBoundsTO;
import com.indi.common.to.es.SkuAttrEsModelTO;
import com.indi.common.to.es.SkuEsModelTO;
import com.indi.common.utils.PageUtils;
import com.indi.common.utils.Query;
import com.indi.common.utils.R;
import com.indi.gulimall.product.dao.SpuInfoDao;
import com.indi.gulimall.product.entity.*;
import com.indi.gulimall.product.feign.CouponFeignService;
import com.indi.gulimall.product.feign.EsFeignService;
import com.indi.gulimall.product.feign.WareFeignService;
import com.indi.gulimall.product.mapstruct.ProductCovertBasic;
import com.indi.gulimall.product.service.*;
import com.indi.gulimall.product.vo.SpuSearchVO;
import com.indi.gulimall.product.vo.spusave.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.stream.Collectors;


@Service("spuInfoService")
@Slf4j
public class SpuInfoServiceImpl extends ServiceImpl<SpuInfoDao, SpuInfoEntity> implements SpuInfoService {
    @Resource
    private SpuInfoDescService spuInfoDescService;

    @Resource
    private SpuImagesService spuImagesService;

    @Resource
    private AttrService attrService;

    @Resource
    private ProductAttrValueService productAttrValueService;

    @Resource
    private SkuInfoService skuInfoService;

    @Resource
    private SkuImagesService skuImagesService;

    @Resource
    private SkuSaleAttrValueService skuSaleAttrValueService;

    @Resource
    private CouponFeignService couponFeignService;

    @Resource
    private WareFeignService wareFeignService;

    @Resource
    private BrandService brandService;

    @Resource
    private CategoryService categoryService;

    @Resource
    private EsFeignService esFeignService;

    @Override
    public PageUtils queryPage(Map<String, Object> params) {
        IPage<SpuInfoEntity> page = this.page(
                new Query<SpuInfoEntity>().getPage(params),
                new QueryWrapper<SpuInfoEntity>()
        );

        return new PageUtils(page);
    }

    @Transactional
    @Override
    public void saveSpuInfo(SpuSaveVO spuSaveVO) {
        // spu基本信息
        SpuInfoEntity spuInfo = ProductCovertBasic.INSTANCE.spuInfoVOToSpuInfo(spuSaveVO);
        this.save(spuInfo);

        Long spuId = spuInfo.getId();

        // spu图片描述
        List<String> descList = spuSaveVO.getDescriptions();
        SpuInfoDescEntity spuInfoDesc = new SpuInfoDescEntity();
        spuInfoDesc.setSpuId(spuId);
        spuInfoDesc.setDescriptions(String.join(",", descList));
        spuInfoDescService.save(spuInfoDesc);

        // spu图片集
        List<String> imgUrlList = spuSaveVO.getImages();
        spuImagesService.saveSpuImages(spuId, imgUrlList);

        // spu规格参数
        List<BaseAttrs> baseAttrs = spuSaveVO.getBaseAttrs();
        List<ProductAttrValueEntity> productAttrValues = baseAttrs.stream().map(baseBaseAttrsVO -> {
            ProductAttrValueEntity attrValue = new ProductAttrValueEntity();
            attrValue.setSpuId(spuId);
            attrValue.setAttrId(baseBaseAttrsVO.getAttrId());

            AttrEntity attr = attrService.getById(baseBaseAttrsVO.getAttrId());
            attrValue.setAttrName(attr.getAttrName());

            attrValue.setAttrValue(baseBaseAttrsVO.getAttrValues());
            attrValue.setQuickShow(baseBaseAttrsVO.getShowDesc());
            return attrValue;
        }).collect(Collectors.toList());
        productAttrValueService.saveBatch(productAttrValues);

        // spu积分信息
        Bounds bounds = spuSaveVO.getBounds();
        SpuBoundsTO spuBoundsTO = ProductCovertBasic.INSTANCE.spuBoundVOToSpuBoundTO(bounds);
        spuBoundsTO.setSpuId(spuInfo.getId());
        R r = couponFeignService.saveSpuBound(spuBoundsTO);
        if (r.getCode().intValue() != 0) {
            log.error("spu积分信息保存失败");
        }

        List<Skus> skuses = spuSaveVO.getSkus();
        if (skuses == null || skuses.size() == 0) {
            return;
        }
        skuses.forEach(skus -> {
            // sku基本信息
            String defaultImgUrl = "";
            List<Images> imagesList = skus.getImages();
            for (Images images : imagesList) {
                if (images.getDefaultImg() == 1) {
                    defaultImgUrl = images.getImgUrl();
                }
            }
            SkuInfoEntity skuInfo = ProductCovertBasic.INSTANCE.skuInfoVOToSkuInfo(skus);
            skuInfo.setSpuId(spuId);
            skuInfo.setCategoryId(spuInfo.getCategoryId());
            skuInfo.setBrandId(spuInfo.getBrandId());
            skuInfo.setSkuDefaultImg(defaultImgUrl);
            skuInfo.setSaleCount(0L);
            skuInfoService.save(skuInfo);

            Long skuId = skuInfo.getSkuId();

            // sku图片信息
            List<SkuImagesEntity> skuImages = imagesList.stream().filter(images -> StringUtils.isNotEmpty(images.getImgUrl())).map(images -> {
                SkuImagesEntity skuImage = new SkuImagesEntity();
                skuImage.setSkuId(skuId);
                skuImage.setImgUrl(images.getImgUrl());
                skuImage.setDefaultImg(images.getDefaultImg());
                return skuImage;
            }).collect(Collectors.toList());
            skuImagesService.saveBatch(skuImages);

            // sku销售属性
            List<Attr> attrs = skus.getAttr();
            List<SkuSaleAttrValueEntity> skuSaleAttrValues = attrs.stream().map(attr -> {
                SkuSaleAttrValueEntity attrValue = ProductCovertBasic.INSTANCE.skuAttrVOToSkuSaleAttrValue(attr);
                attrValue.setSkuId(skuId);
                return attrValue;
            }).collect(Collectors.toList());

            skuSaleAttrValueService.saveBatch(skuSaleAttrValues);

            // sku优惠信息
            if (skus.getFullCount() > 0 || skus.getFullPrice().compareTo(BigDecimal.ZERO) == 1) {
                SkuReductionTO skuReductionTO = ProductCovertBasic.INSTANCE.skuInfoVOToSkuReductionTO(skus);
                skuReductionTO.setSkuId(skuId);
                R r1 = couponFeignService.saveSkuReduction(skuReductionTO);
                if (r1.getCode() != 0) {
                    log.error("sku优惠信息保存失败");
                }
            }
        });

    }

    @Override
    public PageUtils queryPageByCondition(Map<String, Object> params, SpuSearchVO spuSearchVO) {
        QueryWrapper<SpuInfoEntity> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotEmpty(spuSearchVO.getKey())) {
            queryWrapper.and(wrapper -> wrapper.eq("id", spuSearchVO.getKey()).or().like("spu_name", spuSearchVO.getKey()));
        }
        if (spuSearchVO.getStatus() != null) {
            queryWrapper.eq("publish_status", spuSearchVO.getStatus());
        }
        if (spuSearchVO.getBrandId() != null && spuSearchVO.getBrandId().intValue() != 0) {
            queryWrapper.eq("brand_id", spuSearchVO.getBrandId());
        }
        if (spuSearchVO.getCategoryId() != null && spuSearchVO.getCategoryId().intValue() != 0) {
            queryWrapper.eq("category_id", spuSearchVO.getCategoryId());
        }
        IPage<SpuInfoEntity> page = this.page(new Query<SpuInfoEntity>().getPage(params), queryWrapper);
        return new PageUtils(page);
    }

    @Override
    public void spuUp(Long spuId) {
        // 1. 通过 spuId 获取 List<SkuInfoEntity>，定义为 skuInfoList
        List<SkuInfoEntity> skuInfoList = skuInfoService.listBySpuId(spuId);

        // 2. 查询当前 sku 所有可检索的规格属性
        // 2.1 通过 spuId 获取 List<ProductAttrValueEntity> ，定义为 attrValues
        List<ProductAttrValueEntity> attrValues = productAttrValueService.listBySpuId(spuId);

        // 2.2 stream 流：从 attrValues 中提取出 attrId ，转成集合 attrIds
        List<Long> attrIds = attrValues.stream().map(ProductAttrValueEntity::getAttrId).collect(Collectors.toList());

        // 2.3 通过 attrIds ，查询 search_type 为1的 List<Long> searchAttrIds
        List<Long> searchAttrIds = attrService.getSearchAttrIds(attrIds);

        // 2.4 将 searchAttrIds 转成 Set<Long> attrIdSet
        Set<Long> searchAttrIdSet = new HashSet<>(searchAttrIds);

        // 2.5 stream 流：attrValues
        List<SkuAttrEsModelTO> attrs = attrValues.stream().filter(attrValue -> searchAttrIdSet.contains(attrValue.getAttrId()))
                .map(attrValue -> ProductCovertBasic.INSTANCE.attrValueToSkuAttrEsModelTO(attrValue))
                .collect(Collectors.toList());


        // 3. 需要调用仓储服务，查询是否有库存：hasStock
        // 3.1 stream 流：skuInfoList
        // 映射：SkuInfoEntity::getSkuId
        // 收集：转换成 List<Long> skuIds

        List<Long> skuIds = skuInfoList.stream().map(SkuInfoEntity::getSkuId).collect(Collectors.toList());
        Map<Long, Boolean> stockMap = null;
        try {
            R r = wareFeignService.stockOrNot(skuIds);
            stockMap = r.getData(new TypeReference<List<SkuStockTO>>() {
            }).stream().collect(Collectors.toMap(SkuStockTO::getSkuId, SkuStockTO::getStockOrNot));
        } catch (Exception e) {
            log.error("库存服务查询异常：{}", e);
        }

        Map<Long, Boolean> finalStockMap = stockMap;


        // 4. stream流：skuInfoList，遍历项skuInfo
        List<SkuEsModelTO> skuEsModelTOs = skuInfoList.stream().map(skuInfo -> {
            // 将 skuInfo 的属性复制到 SkuEsModel，获取到对象 skuEsModel
            SkuEsModelTO skuEsModelTO = ProductCovertBasic.INSTANCE.skuInfoToSkuModelTO(skuInfo);

            // 有一些复制不过去的属性，需要手动设置
            // 可以直接set：price、skuImg
            skuEsModelTO.setSkuPrice(skuInfo.getPrice());
            skuEsModelTO.setSkuImg(skuInfo.getSkuDefaultImg());

            // 通过brandId、categoryId查询品牌、分类信息设置：brandName、brandImg、categoryName
            BrandEntity brand = brandService.getById(skuInfo.getBrandId());
            skuEsModelTO.setBrandImg(brand.getLogo());
            skuEsModelTO.setBrandName(brand.getName());
            CategoryEntity category = categoryService.getById(skuInfo.getCategoryId());
            skuEsModelTO.setCategoryName(category.getName());

            // attrs：上面已经查出来了
            skuEsModelTO.setAttrs(attrs);

            // hotScore：先设置为0
            skuEsModelTO.setHotScore(0L);

            // hasStock：判断finalSkuHasStock是否为空
            // 为空，则直接赋值为true，不为空，再根据 finalStockMap.get(skuInfo.getSkuId) 设置
            if (finalStockMap == null) {
                skuEsModelTO.setStockOrNot(true);
            } else {
                if (finalStockMap.get(skuInfo.getSkuId()) == null) {
                    skuEsModelTO.setStockOrNot(false);
                } else {
                    skuEsModelTO.setStockOrNot(finalStockMap.get(skuInfo.getSkuId()));
                }
            }
            return skuEsModelTO;
        }).collect(Collectors.toList());


        // 5. 调用远程服务，进行es保存，返回R
        try {
            R r = esFeignService.productStatusUp(skuEsModelTOs);
            if (r.getCode() == 0) {
                // 判断R.getCode()
                // 为0，则根据spuId, 上架状态的code更新商品的状态
                this.updateSpuStatus(spuId, ProductStatusEnum.SPU_UP.getCode());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }

    @Override
    public void updateSpuStatus(Long spuId, int code) {
        SpuInfoEntity spuInfo = new SpuInfoEntity();
        spuInfo.setPublishStatus(code);
        spuInfo.setId(spuId);
        this.updateById(spuInfo);
    }

    @Override
    public SpuInfoEntity getInfoBySkuId(Long skuId) {
        SkuInfoEntity skuInfo = skuInfoService.getById(skuId);
        return this.getById(skuInfo.getSpuId());
    }
}